package net.shopxx.entity;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Transient;

import net.sf.json.JSONArray;
import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig;
import net.shopxx.bean.ProductImage;
import net.shopxx.util.SystemConfigUtil;

import org.apache.commons.lang.StringUtils;
import org.compass.annotations.Index;
import org.compass.annotations.Searchable;
import org.compass.annotations.SearchableProperty;
import org.compass.annotations.Store;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.annotations.MapKey;

/**
 * 实体类 - 商品
 * ============================================================================
 */

@Entity
@Searchable
public class Product extends BaseEntity {

	private static final long serialVersionUID = 4858058186018438872L;
	
	// 重量单位（克、千克、吨）
	public enum WeightUnit {
		g, kg, t
	}

	public static final int MAX_BEST_PRODUCT_LIST_COUNT = 20;// 精品商品列表最大商品数
	public static final int MAX_NEW_PRODUCT_LIST_COUNT = 20;// 新品商品列表最大商品数
	public static final int MAX_HOT_PRODUCT_LIST_COUNT = 20;// 热销商品列表最大商品数
	public static final int DEFAULT_PRODUCT_LIST_PAGE_SIZE = 8;// 商品列表默认每页显示数
	
	private String productSn;// 货号
	private String name;// 商品名称
	private BigDecimal price;// 商品价格
	private BigDecimal marketPrice;// 市场价格
	private Double weight;// 商品重量
	private WeightUnit weightUnit;// 重量单位
	private Integer store;// 商品库存数量
	private Integer freezeStore;// 被占用库存数
	private Integer point;// 积分
	private Boolean isMarketable;// 是否上架
	private Boolean isBest;// 是否为精品商品
	private Boolean isNew;// 是否为新品商品
	private Boolean isHot;// 是否为热销商品
	private String description;// 描述
	private String metaKeywords;// 页面关键词
	private String metaDescription;// 页面描述
	private String htmlFilePath;// HTML静态文件路径
	private String productImageListStore;// 商品图片路径存储
	
	
	private String p0;//镜架材质
	private String p1;//镜架结构
	private String p2;//价格范围
	private String p3;//镜架颜色
	private String p4;//眼镜品牌
	
	private String p5;//
	private String p6;//
	private String p7;//
	private String p8;//
	private String p9;//
	
	private String p10;//
	private String p11;//
	private String p12;//
	private String p13;//
	private String p14;//
	
	private String p15;//
	private String p16;//
	private String p17;//
	private String p18;//
	private String p19;//
	
	private String p20;//
	private String p21;//
	private String p22;//
	private String p23;//
	private String p24;//
	                
	private String p25;//
	private String p26;//
	private String p27;//
	private String p28;//
	private String p29;//

	private String p30;//
	private String p31;//
	private String p32;//
	private String p33;//
	private String p34;//
	                
	private String p35;//
	private String p36;//
	private String p37;//
	private String p38;//
	private String p39;//
	
	
	private String p40;//
	private String p41;//
	private String p42;//
	private String p43;//
	private String p44;//
	                
	private String p45;//
	private String p46;//
	private String p47;//
	private String p48;//
	private String p49;//
	
	private String p50;//
	private String p51;//
	private String p52;//
	private String p53;//
	private String p54;//
	                
	private String p55;//
	private String p56;//
	private String p57;//
	private String p58;//
	private String p59;//
	
	private String p60;//
	private String p61;//
	private String p62;//
	private String p63;//
	private String p64;//
	                
	private String p65;//
	private String p66;//
	private String p67;//
	private String p68;//
	private String p69;//


	private String p70;//
	private String p71;//
	private String p72;//
	private String p73;//
	private String p74;//
	                
	private String p75;//
	private String p76;//
	private String p77;//
	private String p78;//
	private String p79;//
	
	private ProductCategory productCategory;// 商品分类
	private Brand brand;// 品牌
	private ProductType productType;// 商品类型
	private Map<ProductAttribute, String> productAttributeMapStore;// 商品属性存储
	private Set<Member> favoriteMemberSet; // 收藏夹会员
	private Set<CartItem> cartItemSet;// 购物车项
	private Set<OrderItem> orderItemSet;// 订单项
	private Set<DeliveryItem> deliveryItemSet;// 物流项

	@Column(nullable = false, unique = true)
	public String getProductSn() {
		return productSn;
	}

	public void setProductSn(String productSn) {
		this.productSn = productSn;
	}
	
	@SearchableProperty(store = Store.YES)
	@Column(nullable = false)
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@SearchableProperty(store = Store.YES)
	@Column(precision = 15, scale = 5, nullable = false)
	public BigDecimal getPrice() {
		return price;
	}

	// 精度处理
	public void setPrice(BigDecimal price) {
		this.price = SystemConfigUtil.getPriceScaleBigDecimal(price);
	}

	@SearchableProperty(store = Store.YES)
	@Column(precision = 15, scale = 5, nullable = false)
	public BigDecimal getMarketPrice() {
		return marketPrice;
	}

	// 精度处理
	public void setMarketPrice(BigDecimal marketPrice) {
		this.marketPrice = SystemConfigUtil.getPriceScaleBigDecimal(marketPrice);
	}
	
	@Column(nullable = false)
	public Double getWeight() {
		return weight;
	}

	public void setWeight(Double weight) {
		this.weight = weight;
	}

	@Enumerated
	@Column(nullable = false)
	public WeightUnit getWeightUnit() {
		return weightUnit;
	}

	public void setWeightUnit(WeightUnit weightUnit) {
		this.weightUnit = weightUnit;
	}
	
	@SearchableProperty(store = Store.YES)
	public Integer getStore() {
		return store;
	}

	public void setStore(Integer store) {
		this.store = store;
	}
	
	@SearchableProperty(store = Store.YES)
	@Column(nullable = false)
	public Integer getFreezeStore() {
		return freezeStore;
	}

	public void setFreezeStore(Integer freezeStore) {
		this.freezeStore = freezeStore;
	}

	@Column(nullable = false)
	public Integer getPoint() {
		return point;
	}

	public void setPoint(Integer point) {
		if (point == null || point < 0) {
			point = 0;
		}
		this.point = point;
	}

	@SearchableProperty(store = Store.NO)
	@Column(nullable = false)
	public Boolean getIsMarketable() {
		return isMarketable;
	}

	public void setIsMarketable(Boolean isMarketable) {
		this.isMarketable = isMarketable;
	}

	@SearchableProperty(store = Store.NO)
	@Column(nullable = false)
	public Boolean getIsBest() {
		return isBest;
	}

	public void setIsBest(Boolean isBest) {
		this.isBest = isBest;
	}

	@SearchableProperty(store = Store.NO)
	@Column(nullable = false)
	public Boolean getIsNew() {
		return isNew;
	}

	public void setIsNew(Boolean isNew) {
		this.isNew = isNew;
	}

	@SearchableProperty(store = Store.NO)
	@Column(nullable = false)
	public Boolean getIsHot() {
		return isHot;
	}

	public void setIsHot(Boolean isHot) {
		this.isHot = isHot;
	}
	
	@Column(length = 10000)
	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}
	
	@Column(length = 5000)
	public String getMetaKeywords() {
		return metaKeywords;
	}

	public void setMetaKeywords(String metaKeywords) {
		this.metaKeywords = metaKeywords;
	}

	@Column(length = 5000)
	public String getMetaDescription() {
		return metaDescription;
	}

	public void setMetaDescription(String metaDescription) {
		this.metaDescription = metaDescription;
	}
	
	@SearchableProperty(index = Index.NO, store = Store.YES)
	@Column(nullable = false, updatable = false)
	public String getHtmlFilePath() {
		return htmlFilePath;
	}

	public void setHtmlFilePath(String htmlFilePath) {
		this.htmlFilePath = htmlFilePath;
	}

	@SearchableProperty(store = Store.YES)
	@Column(length = 10000)
	public String getProductImageListStore() {
		return productImageListStore;
	}

	public void setProductImageListStore(String productImageListStore) {
		this.productImageListStore = productImageListStore;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(nullable = false)
	public ProductCategory getProductCategory() {
		return productCategory;
	}

	public void setProductCategory(ProductCategory productCategory) {
		this.productCategory = productCategory;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	public Brand getBrand() {
		return brand;
	}

	public void setBrand(Brand brand) {
		this.brand = brand;
	}
	
	@ManyToOne(fetch = FetchType.LAZY)
	public ProductType getProductType() {
		return productType;
	}

	public void setProductType(ProductType productType) {
		this.productType = productType;
	}

	@CollectionOfElements
	@MapKey(targetElement = ProductAttribute.class)
	@LazyCollection(LazyCollectionOption.TRUE)
	@Cascade(value = { CascadeType.DELETE })
	public Map<ProductAttribute, String> getProductAttributeMapStore() {
		return productAttributeMapStore;
	}

	public void setProductAttributeMapStore(Map<ProductAttribute, String> productAttributeMapStore) {
		this.productAttributeMapStore = productAttributeMapStore;
	}

	@ManyToMany(fetch = FetchType.LAZY, mappedBy="favoriteProductSet")
	public Set<Member> getFavoriteMemberSet() {
		return favoriteMemberSet;
	}

	public void setFavoriteMemberSet(Set<Member> favoriteMemberSet) {
		this.favoriteMemberSet = favoriteMemberSet;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "product")
	@Cascade(value = { CascadeType.DELETE })
	public Set<CartItem> getCartItemSet() {
		return cartItemSet;
	}

	public void setCartItemSet(Set<CartItem> cartItemSet) {
		this.cartItemSet = cartItemSet;
	}
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "product")
	public Set<OrderItem> getOrderItemSet() {
		return orderItemSet;
	}

	public void setOrderItemSet(Set<OrderItem> orderItemSet) {
		this.orderItemSet = orderItemSet;
	}

	@OneToMany(mappedBy = "product", fetch = FetchType.LAZY)
	public Set<DeliveryItem> getDeliveryItemSet() {
		return deliveryItemSet;
	}

	public void setDeliveryItemSet(Set<DeliveryItem> deliveryItemSet) {
		this.deliveryItemSet = deliveryItemSet;
	}
	
	// 获取商品图片
	@SuppressWarnings("unchecked")
	@Transient
	public List<ProductImage> getProductImageList() {
		if (StringUtils.isEmpty(productImageListStore)) {
			return null;
		}
		JsonConfig jsonConfig = new JsonConfig();
		jsonConfig.setRootClass(ProductImage.class);
		JSONArray jsonArray = JSONArray.fromObject(productImageListStore);
		return (List<ProductImage>) JSONSerializer.toJava(jsonArray, jsonConfig);
	}
	
	// 设置商品图片
	@Transient
	public void setProductImageList(List<ProductImage> productImageList) {
		if (productImageList == null || productImageList.size() == 0) {
			productImageListStore = null;
			return;
		}
		JSONArray jsonArray = JSONArray.fromObject(productImageList);
		productImageListStore = jsonArray.toString();
	}

	// 获取属性
	@SuppressWarnings("unchecked")
	@Transient
	public Map<ProductAttribute, List<String>> getProductAttributeMap() {
		if (productAttributeMapStore == null || productAttributeMapStore.size() == 0) {
			return null;
		}
		Map<ProductAttribute, List<String>> productAttributeMap = new HashMap<ProductAttribute, List<String>>();
		for (ProductAttribute productAttribute : productAttributeMapStore.keySet()) {
			String productAttributeValueStore = productAttributeMapStore.get(productAttribute);
			if (StringUtils.isNotEmpty(productAttributeValueStore)) {
				JSONArray jsonArray = JSONArray.fromObject(productAttributeMapStore.get(productAttribute));
				productAttributeMap.put(productAttribute, (List<String>) JSONSerializer.toJava(jsonArray));
			} else {
				productAttributeMap.put(productAttribute, null);
			}
		}
		return productAttributeMap;
	}

	// 设置商品属性
	@Transient
	public void setProductAttributeMap(Map<ProductAttribute, List<String>> productAttributeMap) {
		if (productAttributeMap == null || productAttributeMap.size() == 0) {
			productAttributeMapStore = null;
			return;
		}
		Map<ProductAttribute, String> productAttributeMapStore = new HashMap<ProductAttribute, String>();
		for (ProductAttribute productAttribute : productAttributeMap.keySet()) {
			List<String> productAttributeValueList = productAttributeMap.get(productAttribute);
			if (productAttributeValueList != null && productAttributeValueList.size() > 0) {
				JSONArray jsonArray = JSONArray.fromObject(productAttributeValueList);
				productAttributeMapStore.put(productAttribute, jsonArray.toString());
			} else {
				productAttributeMapStore.put(productAttribute, "");
			}
		}
		this.productAttributeMapStore = productAttributeMapStore;
	}
	
	/**
	 * 根据商品图片ID获取商品图片，未找到则返回null
	 * 
	 * @param ProductImage
	 *            ProductImage对象
	 */
	@Transient
	public ProductImage getProductImage(String productImageId) {
		List<ProductImage> productImageList = getProductImageList();
		for (ProductImage productImage : productImageList) {
			if (StringUtils.equals(productImageId, productImage.getId())) {
				return productImage;
			}
		}
		return null;
	}
	
	/**
	 * 商品是否缺货
	 */
	@Transient
	public boolean getIsOutOfStock() {
		if (store != null && freezeStore >= store) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 获取优惠价格，若member对象为null则返回原价格
	 */
	@Transient
	public BigDecimal getPreferentialPrice(Member member) {
		if (member != null) {
			BigDecimal preferentialPrice = price.multiply(new BigDecimal(member.getMemberRank().getPreferentialScale().toString()).divide(new BigDecimal("100")));
			return SystemConfigUtil.getPriceScaleBigDecimal(preferentialPrice);
		} else {
			return price;
		}
	}

	public String getP0() {
		return p0;
	}

	public void setP0(String p0) {
		this.p0 = p0;
	}

	public String getP1() {
		return p1;
	}

	public void setP1(String p1) {
		this.p1 = p1;
	}

	public String getP2() {
		return p2;
	}

	public void setP2(String p2) {
		this.p2 = p2;
	}

	public String getP3() {
		return p3;
	}

	public void setP3(String p3) {
		this.p3 = p3;
	}

	public String getP4() {
		return p4;
	}

	public void setP4(String p4) {
		this.p4 = p4;
	}

	public String getP5() {
		return p5;
	}

	public void setP5(String p5) {
		this.p5 = p5;
	}

	public String getP6() {
		return p6;
	}

	public void setP6(String p6) {
		this.p6 = p6;
	}

	public String getP7() {
		return p7;
	}

	public void setP7(String p7) {
		this.p7 = p7;
	}

	public String getP8() {
		return p8;
	}

	public void setP8(String p8) {
		this.p8 = p8;
	}

	public String getP9() {
		return p9;
	}

	public void setP9(String p9) {
		this.p9 = p9;
	}

	public String getP10() {
		return p10;
	}

	public void setP10(String p10) {
		this.p10 = p10;
	}

	public String getP11() {
		return p11;
	}

	public void setP11(String p11) {
		this.p11 = p11;
	}

	public String getP12() {
		return p12;
	}

	public void setP12(String p12) {
		this.p12 = p12;
	}

	public String getP13() {
		return p13;
	}

	public void setP13(String p13) {
		this.p13 = p13;
	}

	public String getP14() {
		return p14;
	}

	public void setP14(String p14) {
		this.p14 = p14;
	}

	public String getP15() {
		return p15;
	}

	public void setP15(String p15) {
		this.p15 = p15;
	}

	public String getP16() {
		return p16;
	}

	public void setP16(String p16) {
		this.p16 = p16;
	}

	public String getP17() {
		return p17;
	}

	public void setP17(String p17) {
		this.p17 = p17;
	}

	public String getP18() {
		return p18;
	}

	public void setP18(String p18) {
		this.p18 = p18;
	}

	public String getP19() {
		return p19;
	}

	public void setP19(String p19) {
		this.p19 = p19;
	}

	public String getP20() {
		return p20;
	}

	public void setP20(String p20) {
		this.p20 = p20;
	}

	public String getP21() {
		return p21;
	}

	public void setP21(String p21) {
		this.p21 = p21;
	}

	public String getP22() {
		return p22;
	}

	public void setP22(String p22) {
		this.p22 = p22;
	}

	public String getP23() {
		return p23;
	}

	public void setP23(String p23) {
		this.p23 = p23;
	}

	public String getP24() {
		return p24;
	}

	public void setP24(String p24) {
		this.p24 = p24;
	}

	public String getP25() {
		return p25;
	}

	public void setP25(String p25) {
		this.p25 = p25;
	}

	public String getP26() {
		return p26;
	}

	public void setP26(String p26) {
		this.p26 = p26;
	}

	public String getP27() {
		return p27;
	}

	public void setP27(String p27) {
		this.p27 = p27;
	}

	public String getP28() {
		return p28;
	}

	public void setP28(String p28) {
		this.p28 = p28;
	}

	public String getP29() {
		return p29;
	}

	public void setP29(String p29) {
		this.p29 = p29;
	}

	public String getP30() {
		return p30;
	}

	public void setP30(String p30) {
		this.p30 = p30;
	}

	public String getP31() {
		return p31;
	}

	public void setP31(String p31) {
		this.p31 = p31;
	}

	public String getP32() {
		return p32;
	}

	public void setP32(String p32) {
		this.p32 = p32;
	}

	public String getP33() {
		return p33;
	}

	public void setP33(String p33) {
		this.p33 = p33;
	}

	public String getP34() {
		return p34;
	}

	public void setP34(String p34) {
		this.p34 = p34;
	}

	public String getP35() {
		return p35;
	}

	public void setP35(String p35) {
		this.p35 = p35;
	}

	public String getP36() {
		return p36;
	}

	public void setP36(String p36) {
		this.p36 = p36;
	}

	public String getP37() {
		return p37;
	}

	public void setP37(String p37) {
		this.p37 = p37;
	}

	public String getP38() {
		return p38;
	}

	public void setP38(String p38) {
		this.p38 = p38;
	}

	public String getP39() {
		return p39;
	}

	public void setP39(String p39) {
		this.p39 = p39;
	}

	public String getP40() {
		return p40;
	}

	public void setP40(String p40) {
		this.p40 = p40;
	}

	public String getP41() {
		return p41;
	}

	public void setP41(String p41) {
		this.p41 = p41;
	}

	public String getP42() {
		return p42;
	}

	public void setP42(String p42) {
		this.p42 = p42;
	}

	public String getP43() {
		return p43;
	}

	public void setP43(String p43) {
		this.p43 = p43;
	}

	public String getP44() {
		return p44;
	}

	public void setP44(String p44) {
		this.p44 = p44;
	}

	public String getP45() {
		return p45;
	}

	public void setP45(String p45) {
		this.p45 = p45;
	}

	public String getP46() {
		return p46;
	}

	public void setP46(String p46) {
		this.p46 = p46;
	}

	public String getP47() {
		return p47;
	}

	public void setP47(String p47) {
		this.p47 = p47;
	}

	public String getP48() {
		return p48;
	}

	public void setP48(String p48) {
		this.p48 = p48;
	}

	public String getP49() {
		return p49;
	}

	public void setP49(String p49) {
		this.p49 = p49;
	}

	public String getP50() {
		return p50;
	}

	public void setP50(String p50) {
		this.p50 = p50;
	}

	public String getP51() {
		return p51;
	}

	public void setP51(String p51) {
		this.p51 = p51;
	}

	public String getP52() {
		return p52;
	}

	public void setP52(String p52) {
		this.p52 = p52;
	}

	public String getP53() {
		return p53;
	}

	public void setP53(String p53) {
		this.p53 = p53;
	}

	public String getP54() {
		return p54;
	}

	public void setP54(String p54) {
		this.p54 = p54;
	}

	public String getP55() {
		return p55;
	}

	public void setP55(String p55) {
		this.p55 = p55;
	}

	public String getP56() {
		return p56;
	}

	public void setP56(String p56) {
		this.p56 = p56;
	}

	public String getP57() {
		return p57;
	}

	public void setP57(String p57) {
		this.p57 = p57;
	}

	public String getP58() {
		return p58;
	}

	public void setP58(String p58) {
		this.p58 = p58;
	}

	public String getP59() {
		return p59;
	}

	public void setP59(String p59) {
		this.p59 = p59;
	}

	public String getP60() {
		return p60;
	}

	public void setP60(String p60) {
		this.p60 = p60;
	}

	public String getP61() {
		return p61;
	}

	public void setP61(String p61) {
		this.p61 = p61;
	}

	public String getP62() {
		return p62;
	}

	public void setP62(String p62) {
		this.p62 = p62;
	}

	public String getP63() {
		return p63;
	}

	public void setP63(String p63) {
		this.p63 = p63;
	}

	public String getP64() {
		return p64;
	}

	public void setP64(String p64) {
		this.p64 = p64;
	}

	public String getP65() {
		return p65;
	}

	public void setP65(String p65) {
		this.p65 = p65;
	}

	public String getP66() {
		return p66;
	}

	public void setP66(String p66) {
		this.p66 = p66;
	}

	public String getP67() {
		return p67;
	}

	public void setP67(String p67) {
		this.p67 = p67;
	}

	public String getP68() {
		return p68;
	}

	public void setP68(String p68) {
		this.p68 = p68;
	}

	public String getP69() {
		return p69;
	}

	public void setP69(String p69) {
		this.p69 = p69;
	}

	public String getP70() {
		return p70;
	}

	public void setP70(String p70) {
		this.p70 = p70;
	}

	public String getP71() {
		return p71;
	}

	public void setP71(String p71) {
		this.p71 = p71;
	}

	public String getP72() {
		return p72;
	}

	public void setP72(String p72) {
		this.p72 = p72;
	}

	public String getP73() {
		return p73;
	}

	public void setP73(String p73) {
		this.p73 = p73;
	}

	public String getP74() {
		return p74;
	}

	public void setP74(String p74) {
		this.p74 = p74;
	}

	public String getP75() {
		return p75;
	}

	public void setP75(String p75) {
		this.p75 = p75;
	}

	public String getP76() {
		return p76;
	}

	public void setP76(String p76) {
		this.p76 = p76;
	}

	public String getP77() {
		return p77;
	}

	public void setP77(String p77) {
		this.p77 = p77;
	}

	public String getP78() {
		return p78;
	}

	public void setP78(String p78) {
		this.p78 = p78;
	}

	public String getP79() {
		return p79;
	}

	public void setP79(String p79) {
		this.p79 = p79;
	}

	public static long getSerialVersionUID() {
		return serialVersionUID;
	}

	public static int getMAX_BEST_PRODUCT_LIST_COUNT() {
		return MAX_BEST_PRODUCT_LIST_COUNT;
	}

	public static int getMAX_NEW_PRODUCT_LIST_COUNT() {
		return MAX_NEW_PRODUCT_LIST_COUNT;
	}

	public static int getMAX_HOT_PRODUCT_LIST_COUNT() {
		return MAX_HOT_PRODUCT_LIST_COUNT;
	}

	public static int getDEFAULT_PRODUCT_LIST_PAGE_SIZE() {
		return DEFAULT_PRODUCT_LIST_PAGE_SIZE;
	}

}